﻿    using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Xml.Linq;
using System.IO;
using System.ComponentModel;

namespace TMS
{
    public class UsuarioXMLManager : XMLBaseManager
    {
        private static UsuarioXMLManager _instancia;

        public static UsuarioXMLManager getInstancia()
        {
            if (_instancia == null)
            {
                _instancia = new UsuarioXMLManager();
            }
            return _instancia;
        }

        private UsuarioXMLManager()
        {
            nombreRoot = "Usuarios";
            nombreArchivo = nombreRoot + ".xml";
        }

        public long addUsuario(Usuario pUsuario)
        {
            XDocument xDoc = loadDoc(); //Carga el documento.
            XElement usuarios = xDoc.Root; //Obtiene la raiz del documento XML.
            XElement usuario = new XElement("Usuario"); //Genera un nuevo elemento.
            usuario.SetAttributeValue("Id", "" + pUsuario.NroUsuario); //Agrega numero de usuario como atributo.
            usuario.SetAttributeValue("Estado", "" + pUsuario.Estado); //Agrega estado del usuario (activo o inactivo).
            usuario.SetElementValue("Nombre", pUsuario.Nombre); //Agrega el nombre del usuario.
            usuario.SetElementValue("Nick", pUsuario.Nick); //Agrega el nombre de usuario.
            usuario.SetElementValue("Password", pUsuario.Password); //Agrega la contrase;a.
            usuario.SetElementValue("Mail", pUsuario.Mail); //Agrega el e-mail.
            /*usuario.SetElementValue("Tipo", pUsuario.Tipo + "");*/
            usuarios.Add(usuario); //Agrega el elemento definido antes a la raiz del documento.
            saveDoc(xDoc); //Guarda el documento.
            return long.Parse(usuario.Attribute("Id").Value);
        }
        public void updateUsuario(Usuario pUsuario)
        {
            XDocument xDoc = loadDoc();
            XElement usuario = xDoc.Root.Elements().Single(a => (long)a.Attribute("Id") == pUsuario.NroUsuario);
            usuario.SetElementValue("Nick", pUsuario.Nick); //Agrega el nombre de usuario.
            usuario.SetElementValue("Password", pUsuario.Password); //Agrega la contrase;a.
            usuario.SetElementValue("Mail", pUsuario.Mail); //Agrega el e-mail.
            
            /* 
             * El codigo siguiente recorre el objeto que se recibe como parametro para saber si contiene
             * valores asignados x el constructor en los atributos Estado y Nombre,
             * permitiendo que la funcion realice la modificacion, independientemente del constructor utilizado 
             * para instanciar la clase Usuario.
             */
            foreach(PropertyDescriptor descrip in TypeDescriptor.GetProperties(pUsuario))
            { 
                if(descrip.Name == "Estado" && "" + descrip.GetValue(pUsuario) != "")
                {
                    usuario.SetAttributeValue("Estado", "" + pUsuario.Estado); //Agrega estado del usuario (activo o inactivo).
                }
                else if(descrip.Name == "Nombre" && ""+ descrip.GetValue(pUsuario) != "")  
                {
                    usuario.SetElementValue("Nombre", "" + pUsuario.Nombre); //Agrega el nombre del usuario
                }      
            }
            saveDoc(xDoc);
        }
        public void altaUsuario(long pId)
        {
            /* 
             * Se cambia el estado Inactivo, asignado por defecto al registrarse el usuario,
             * por Activo.
             */ 
            XDocument xDoc = loadDoc();
            XElement usuario = xDoc.Root.Elements().Single(a => (long)a.Attribute("Id") == pId);
            usuario.SetAttributeValue("Estado", "Activo");
            saveDoc(xDoc);
        }
        public void eliminarUsuario(long pId)
        {
            /*
             * Esta funcion en realidad no elimina al usuario del sistema, sino que lo desactiva,
             * quedando sus datos almacenados en el sistema.
             * Esto es para que todos los errores y comentarios posteados en el sistema, que conservaran 
             * validez a pesar de la baja del usuario, no queden huerfanos.
             */
            XDocument xDoc = loadDoc();
            XElement usuario = xDoc.Root.Elements().Single(a => (long)a.Attribute("Id") == pId);
            usuario.SetAttributeValue("Estado", "Eliminado");
            saveDoc(xDoc);
        }
        public List<Usuario> getListActivos()
        {
            /*
             * Realiza iteraciones dentro de una lista de usuarios cuyo estado es Activo, y por cada uno 
             * de los items de esa lista, crea una instancia del tipo Usuario, asignandole los valores y
             * atributos de los elementos encontrados y agregandola a una lista del mismo tipo que devuelve al final.
             */ 
            List<Usuario> lstActivos = new List<Usuario>();
            XDocument xDoc = loadDoc();
            foreach (XElement xel in xDoc.Root.Elements().Where(u => (string)u.Attribute("Estado").Value == "" + usuarioEstado.Activo))
            {
                Usuario u = new Usuario();
                u.NroUsuario = long.Parse(xel.Attribute("Id").Value);
                u.Nombre = xel.Element("Nombre").Value;
                u.Nick = xel.Element("Nick").Value;
                u.Mail = xel.Element("Mail").Value;
                lstActivos.Add(u);
            }
            return lstActivos;
        }
        public List<Usuario> getListInactivos()
        {
            /*
             * Realiza iteraciones dentro de una lista de usuarios cuyo estado es Inactivo, y por cada uno 
             * de los items de esa lista, crea una instancia del tipo Usuario, asignandole los valores y
             * atributos de los elementos encontrados y agregandola a una lista del mismo tipo que devuelve al final.
             */
            List<Usuario> lstInactivos = new List<Usuario>();
            XDocument xDoc = loadDoc();
            foreach (XElement xel in xDoc.Root.Elements().Where(u => (string)u.Attribute("Estado").Value == "" + usuarioEstado.Inactivo))
            {
                Usuario u = new Usuario();
                u.NroUsuario = long.Parse(xel.Attribute("Id").Value);
                u.Nombre = xel.Element("Nombre").Value;
                u.Nick = xel.Element("Nick").Value;
                u.Mail = xel.Element("Mail").Value;
                lstInactivos.Add(u);
            }
            return lstInactivos;
        }
        public List<Usuario> getListEliminados()
        {
            /*
             * Realiza iteraciones dentro de una lista de usuarios cuyo estado es Eliminado, y por cada uno 
             * de los items de esa lista, crea una instancia del tipo Usuario, asignandole los valores y
             * atributos de los elementos encontrados y agregandola a una lista del mismo tipo que devuelve al final.
             */
            List<Usuario> lstEliminados = new List<Usuario>();
            XDocument xDoc = loadDoc();
            foreach (XElement xel in xDoc.Root.Elements().Where(u => (string)u.Attribute("Estado").Value == "" + usuarioEstado.Eliminado))
            {
                Usuario u = new Usuario();
                u.NroUsuario = long.Parse(xel.Attribute("Id").Value);
                u.Nombre = xel.Element("Nombre").Value;
                u.Nick = xel.Element("Nick").Value;
                u.Mail = xel.Element("Mail").Value;
                lstEliminados.Add(u);
            }
            return lstEliminados;
        }
        public Usuario verificarPass(string pNic, string pPass)
        { 
            Usuario u = new Usuario();
            try
            {
                XDocument xDoc = loadDoc();
                XElement xEl = xDoc.Root.Elements().Single(a => (string)a.Element("Nick") == pNic && (string)a.Element("Password") == pPass && (string)a.Attribute("Estado").Value == "Activo");

                if (xEl != null)
                {
                    u.NroUsuario = long.Parse(xEl.Attribute("Id").Value);
                    u.Nombre = xEl.Element("Nombre").Value;
                    u.Nick = xEl.Element("Nick").Value;
                    //u.Password = xEl.Element("Password").Value;
                    /*u.Tipo = (tipoUsuario)Enum.Parse(typeof(tipoUsuario), xEl.Element("Tipo").Value);*/
                }
            }
            catch (InvalidOperationException)
            { 
                // Si no existe el elemento xml.
                u = null;
            }
            return u;
        }
        public string getTipoUsuario(long pId)
        {
            /*
             * Recibe como parametro el Id de un usuario y consulta en los archivos XML Administradores, Developers y Testers
             * si tienen almacenado un elemento con dicho Id.
             * Luego devuelve el tipo de usuario dependiendo del documento XML donde se encontro el Id.
             */ 
            string tipo = "";
            if(AdministradorXMLManager.getInstancia().existsById(pId))
            {
                tipo = "" + tipoUsuario.Administrador;
            }
            else if(DeveloperXMLManager.getInstancia().existsById(pId))
            {
                tipo = "" + tipoUsuario.Developer;
            }
            else if (TesterXMLManager.getInstancia().existsById(pId))
            {
                tipo = "" + tipoUsuario.Tester;
            }

            return tipo;
        }
        public Usuario getUsuarioById(long pId)
        {
            Usuario usu = null;
            try
            {
                XDocument xDoc = loadDoc();
                XElement unUsuario = xDoc.Root.Elements().Single(u => long.Parse(u.Attribute("Id").Value) == pId);
                if (unUsuario != null)
                {
                    usu = new Usuario();
                    usu.NroUsuario = pId;
                    usu.Nombre = unUsuario.Element("Nombre").Value;
                    usu.Nick = unUsuario.Element("Nick").Value;
                    usu.Mail = unUsuario.Element("Mail").Value;
                    usu.Password = unUsuario.Element("Password").Value;
                    usu.Estado = (usuarioEstado)Enum.Parse(typeof(usuarioEstado), unUsuario.Attribute("Estado").Value);
                }
            }
            catch (InvalidOperationException e)
            {
                usu = null;
            }
            return usu;
        }
        public bool existeUsuario(string pNic)
        {
            /*
             * Comprueba que no exista un usuario registrado con ese Nick.
             */ 
            bool existe = false;
            XDocument xDoc = loadDoc(); //Carga el documento.
            try
            {
                XElement xEl = xDoc.Root.Elements().Single(a => (string)a.Element("Nick") == pNic);
                if (xEl != null)
                {
                    existe = true;
                }
            }
            catch (InvalidOperationException)
            {
                existe = false;
            }
            return existe;
        }
    }

}
